import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import models.LocationUi
import models.UserRepository
import models.admin.AdminEvent
import models.admin.AdminViewState
import models.shared.UserUi

class UserAdminViewModel(
    private val userRepository: UserRepository,
    private val locationsRepository: LocationsRepository
) : BaseViewModel<AdminViewState, AdminEvent>(
    initialState = AdminViewState()
) {
    override fun obtainEvent(event: AdminEvent) {
        when (event) {
            AdminEvent.LoadUsers -> {
                loadUsers()
                loadLocations()
            }

            is AdminEvent.Delete -> {
                deleteUser(event.id)
            }

            is AdminEvent.UpdateLocation -> {
                updateLocation(event.id, event.locationId)
            }

            is AdminEvent.UpdateRole -> {
                updateRole(event.id, event.role)
            }

            is AdminEvent.SelectUser -> {
                updateState {
                    it.copy(selectedUser = event.user)
                }
            }
        }
    }

    private fun loadUsers() {
        updateState { it.copy(loadingStatus = LoadingStatus.Loading) }
        viewModelScope.launch {
            userRepository.users()
                .onSuccess { users ->
                    updateState {
                        it.copy(
                            users = users.map { u -> UserUi.from(u) },
                            loadingStatus = LoadingStatus.Idle
                        )
                    }
                }
                .onFailure { t ->
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Error(t.message)
                        )
                    }
                }
        }
    }

    private fun loadLocations() {
        updateState { it.copy(loadingStatus = LoadingStatus.Loading) }
        viewModelScope.launch {
            locationsRepository.locations()
                .onSuccess { locations ->
                    updateState {
                        it.copy(
                            locations = locations.map { l -> LocationUi.from(l) },
                            loadingStatus = LoadingStatus.Idle
                        )
                    }
                    loadUsers()
                }
                .onFailure { t ->
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Error(t.message)
                        )
                    }
                }
        }
    }

    private fun deleteUser(id: Int) {
        updateState { it.copy(loadingStatus = LoadingStatus.Loading) }
        viewModelScope.launch {
            userRepository.delete(id)
                .onSuccess {
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Idle,
                            users = it.users.filter { u -> u.id != id }
                        )
                    }
                    loadUsers()
                }
                .onFailure { t ->
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Error(t.message)
                        )
                    }
                }
        }
    }

    private fun updateRole(id: Int, role: UserUi.Role) {
        updateState { it.copy(loadingStatus = LoadingStatus.Loading) }
        viewModelScope.launch {
            userRepository.updateRole(id, role.name)
                .onSuccess {
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Idle,
                            users = it.users.map { u ->
                                if (u.id == id) {
                                    u.copy(role = role)
                                } else {
                                    u
                                }
                            }
                        )
                    }
                    loadUsers()
                }
                .onFailure { t ->
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Error(t.message)
                        )
                    }
                }
        }
    }

    private fun updateLocation(id: Int, locationId: Int) {
        updateState { it.copy(loadingStatus = LoadingStatus.Loading) }
        viewModelScope.launch {
            userRepository.updateLocation(id, locationId)
                .onSuccess {
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Idle,
                            users = it.users.map { u ->
                                if (u.id == id) {
                                    u.copy(location = it.locations.find { l -> l.id == locationId })
                                } else {
                                    u
                                }
                            }
                        )
                    }
                }
                .onFailure { t ->
                    updateState {
                        it.copy(
                            loadingStatus = LoadingStatus.Error(t.message)
                        )
                    }
                }
        }
    }
}